package com.cetccloud.ap.proxy.channel.cossDomain.s30.channel.recv;

import com.cetccloud.ap.config.ProxyConfig;
import com.cetccloud.ap.proxy.channel.cossDomain.s30.S30Config;
import com.sun.jna.Pointer;
import com.thunisoft.exchange.gateway.protocol.entity.GatewayAppNode;
import com.thunisoft.exchange.gateway.protocol.entity.GatewayExchangeNode;
import com.wish.xsagent.JXSAgent;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @ClassName S30RecvChannel
 * @Description
 * @Author superz
 * @Date 2021/4/23 10:34
 * @Version 1.0
 **/
@Slf4j
@Component
public class S30RecvChannel {

    @Autowired
    private ProxyConfig proxyConfig;

    @Autowired
    private S30Config s30Config;

    @Autowired
    private Recv4RecvHandle recv4RecvHandle;

    @Autowired
    private Conn4RecvHandle conn4RecvHandle;

    private Pointer self;

    @Getter
    private Collection<GatewayExchangeNode> exchangeNodes = new ArrayList<>();

    @Getter
    private Map<String, String> proxyZoneAppMap = new HashMap<>();

    @Getter
    private Map<String, String> proxyAppZoneMap = new HashMap<>();

    public void start() {
        if (proxyConfig.isMock()) {
            log.info("### S30RecvChannel start [mock state] ###");
            return;
        }
        log.info("### S30RecvChannel start ###, appId: {}, ip: {}, port: {}", s30Config.getProxy().getAppId(), s30Config.getPeer().getRecv().getIp(), Short.parseShort(s30Config.getPeer().getRecv().getPort()));
        try {
            self = JXSAgent.INSTANCE.initialize(s30Config.getProxy().getAppId(), s30Config.getPeer().getRecv().getIp(), Short.parseShort(s30Config.getPeer().getRecv().getPort()));
            JXSAgent.INSTANCE.set_log_level(self, 1);
            JXSAgent.INSTANCE.disable_crypto(self);
            JXSAgent.INSTANCE.set_recv_handle(self, recv4RecvHandle);
            JXSAgent.INSTANCE.set_conn_handle(self, conn4RecvHandle);
            JXSAgent.INSTANCE.start_up(self);
            log.info("### S30RecvChannel start ### end");
        } catch (Throwable t) {
            log.error("### S30RecvChannel start ### error", t);
        }
    }

    public boolean isConnected() {
        return conn4RecvHandle.isConnected();
    }

    public synchronized void setExchangeNodes(List<GatewayExchangeNode> exchangeNodes) {
        this.exchangeNodes = Collections.unmodifiableCollection(exchangeNodes);
        if (CollectionUtils.isNotEmpty(exchangeNodes)) {
            for (GatewayExchangeNode gatewayExchangeNode : exchangeNodes) {
                String zoneId = gatewayExchangeNode.getZone_id();
                ArrayList<GatewayAppNode> apps = gatewayExchangeNode.getApps();
                if (CollectionUtils.isNotEmpty(apps)) {
                    for (GatewayAppNode appNode : apps) {
                        if (StringUtils.equals(s30Config.getProxy().getAppAlias(), appNode.getAlias())) {
                            proxyZoneAppMap.put(zoneId, appNode.getApp_id());
                            proxyAppZoneMap.put(appNode.getApp_id(), zoneId);
                            break;
                        }
                    }
                }
            }
        }
    }

    public void stop() {
        if (proxyConfig.isMock()) {
            log.info("### S30RecvChannel stop [mock state] ###");
            return;
        }
        log.info("### S30RecvChannel stop ###");
        JXSAgent.INSTANCE.shut_down(self);
        JXSAgent.INSTANCE.finalize(self);
    }
}
